home *** CD-ROM | disk | FTP | other *** search
/ Young Minds / Young Minds Interactive CD-ROM.ISO / qix / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-01-28  |  9.7 KB  |  350 lines

  1. /*
  2.  * The game of Qix for the Sun3 workstation running Sunview (probably 3.0)--
  3.  * Appearance ONLY shamelessly stolen from the real video game wonderfully
  4.  * and admirably written by individual(s) unknown at Taito Corp (I think).
  5.  *
  6.  * Copyright 1987 by Dan Heller (island!argv@sun.com or argv@spam.istc.sri.com)
  7.  *
  8.  * Various polygon filling routines written by
  9.  *   -- Dan "Sky" Shultz (island!sky@sun.com)  and
  10.  *   -- Don Hatch (splat%ucscb@ucscc.ucsc.edu [fall, 1987])
  11.  *      additional help (general debugging, recursive polyfill)
  12.  *
  13.  * Move mouse to go in direction.  Left button does fast draw. Middle does
  14.  * slow draw.  Rogue/vi keys moves -- upper case draws.  There is no slow
  15.  * draw for keyboard input.
  16.  *
  17.  * There is not yet a stage where you split two qix.
  18.  *
  19.  * Sparx don't do what they should; they move randomly and without purpose.
  20.  * They only kill the user -- there are no aggressive sparx.
  21.  *
  22.  * The qix will sometimes get into an infinite loop trying to get itself
  23.  * or a portion of itself out of a place it shouldn't be (closed area).
  24.  */
  25.  
  26. #include "qix.h"
  27.  
  28. /* the main icon for when the tool is closed */
  29. short qix_icon_dat[] = {
  30. #include "qix.icon"
  31. };
  32. DEFINE_ICON_FROM_IMAGE(qix_icon, qix_icon_dat);
  33.  
  34. int (*old_repaint_func)();
  35.  
  36.  
  37. redraw(args)
  38. {
  39.     stop_timer();
  40.     (*old_repaint_func)(&args);
  41.     start_timer();
  42. }
  43.  
  44. main(argc, argv)
  45. char *argv[];
  46. {
  47.     int catch();
  48.     char **newargv = argv;
  49.  
  50.     (void) signal(SIGBUS, catch);
  51.     (void) signal(SIGSEGV, catch);
  52.     (void) signal(SIGXCPU, catch);
  53.  
  54. #ifdef DEBUG
  55.     /*
  56.      * specify debug levels "-d level"
  57.      * a level of 2 prints polygon fill info. 4 disables spark-generation
  58.      * but doesn't kill current sparks.  debug level 1 does prints things...
  59.      */
  60.     while (*++newargv)
  61.     if (!strcmp(*newargv, "-q"))
  62.         no_qix_kill = 1;
  63.     else if (!strcmp(*newargv, "-d"))
  64.         debug = (*++newargv) ? atoi(*newargv) : 1;
  65. #endif DEBUG
  66.  
  67.     frame = window_create(NULL, FRAME,
  68.     FRAME_LABEL, argv[0],
  69.     WIN_X, 250, WIN_Y, 45,
  70.     FRAME_ICON, &qix_icon,
  71.     FRAME_ARGS, argc, argv,
  72.     FRAME_NO_CONFIRM, TRUE,
  73.     0);
  74.  
  75.     Draw = window_create(frame, CANVAS,
  76.     WIN_HEIGHT, BOARD_HEIGHT_IN_PIXELS,
  77.     WIN_WIDTH,  BOARD_WIDTH_IN_PIXELS,
  78.     WIN_EVENT_PROC, move_joystick,
  79.     0);
  80.  
  81.     draw_win = canvas_pixwin(Draw);
  82.     window_set(Draw,
  83.     CANVAS_FAST_MONO, TRUE,
  84.     WIN_CONSUME_PICK_EVENTS,
  85.         WIN_MOUSE_BUTTONS,
  86.         0,
  87.     WIN_CONSUME_KBD_EVENTS,
  88.         WIN_ASCII_EVENTS,
  89.         SHIFT_CTRL, SHIFT_META,
  90.         0,
  91.     WIN_INPUT_DESIGNEE, window_get(Draw, WIN_DEVICE_NUMBER),
  92.     0);
  93.  
  94.     Joystick = window_create(frame, CANVAS,
  95.     WIN_X, 0,
  96.     WIN_BELOW, Draw,
  97.     WIN_HEIGHT, 68,
  98.     WIN_WIDTH, WIN_EXTEND_TO_EDGE,
  99.     0);
  100.     joystick_win = canvas_pixwin(Joystick);
  101.  
  102.     window_fit(frame);
  103.  
  104.     if (!(small_font = pf_open("/usr/people/argv/computer.14")) &&
  105.     !(small_font = pf_default()) ||
  106.     !(big_font = pf_open("/usr/lib/fonts/fixedwidthfonts/serif.r.16")) &&
  107.     !(big_font = pf_default()))
  108.     perror("can't open default font"), exit(1);
  109.  
  110.     level = -2; /* two screens before player may split two qix */
  111.     moving = NO_MOVE;
  112.     fast = 1,
  113.  
  114.     srandom(time(0));
  115.     srand(time(0));
  116.     update_score();
  117.  
  118.     init_qix();
  119.     draw_joystick();
  120.     pw_text(joystick_win, 92, 24, PIX_SRC, small_font, "Fast  Slow");
  121.     play_mode = SHOW_SCORES;
  122.     update_score();
  123.     score_board(TRUE, FALSE);
  124.     time_left = 100; /* timeout before next demo mode switch */
  125.     (void) signal(SIGALRM, move_pen);
  126.     old_repaint_func = (int(*)())window_get(frame, CANVAS_REPAINT_PROC);
  127.     window_set(frame, CANVAS_REPAINT_PROC, redraw, 0);
  128.     start_timer();
  129.  
  130.     window_main_loop(frame);        /* main loop to read input */
  131.     exit(0);
  132. }
  133.  
  134. clear_board()
  135. {
  136.     register int x, y;
  137.  
  138.     clear_sparks();
  139.     area_closed = 0;
  140.  
  141.     pen_x = (BOARD_WIDTH-1)/2, pen_y = BOARD_HEIGHT-1;
  142.     remove_msgs(1);
  143.  
  144.     /* give left->right sweeping effect like the real game */
  145.     for (x = 0; x < BOARD_WIDTH_IN_PIXELS; x++)
  146.     draw(x, 0, x, BOARD_HEIGHT_IN_PIXELS-1, PIX_CLR);
  147.  
  148.     box(convert_x(0), convert_y(0),
  149.     convert_x(BOARD_WIDTH-1), convert_y(BOARD_HEIGHT-1), PIX_SRC);
  150.  
  151.     /* clear the interior of the board */
  152.     for (x = 1; x < BOARD_WIDTH-1; x++)
  153.     for (y = 1; y < BOARD_HEIGHT-1; y++)
  154.         board[x][y] = 0;
  155.  
  156.     for (x = 1; x < BOARD_WIDTH-1; x++) {
  157.     board[x][0] = CL_LN_LF | CL_LN_RT | OLD_LINE | CL_PNT_TOP;
  158.     board[x][BOARD_HEIGHT-1] = CL_LN_LF | CL_LN_RT | OLD_LINE | CL_PNT_BOT;
  159.     }
  160.  
  161.     for (y = 1; y < BOARD_HEIGHT-1; y++) {
  162.     board[0][y] = CL_LN_UP | CL_LN_DN | OLD_LINE | CL_PNT_LEFT;
  163.     board[BOARD_WIDTH-1][y] = CL_LN_UP | CL_LN_DN | OLD_LINE | CL_PNT_RIGHT;
  164.     }
  165.     /* set the corners explicitly */
  166.     board[0][0] = (CL_LN_DN | CL_LN_RT | CL_PNT_TOP | CL_PNT_LEFT | OLD_LINE);
  167.     board[0][BOARD_HEIGHT-1] =
  168.     (CL_LN_UP | CL_LN_RT | CL_PNT_BOT | CL_PNT_LEFT | OLD_LINE);
  169.     board[BOARD_WIDTH-1][0] =
  170.         (CL_LN_DN | CL_LN_LF | CL_PNT_TOP | CL_PNT_RIGHT | OLD_LINE);
  171.     board[BOARD_WIDTH-1][BOARD_HEIGHT-1] =
  172.     (CL_LN_UP | CL_LN_LF | CL_PNT_BOT | CL_PNT_RIGHT | OLD_LINE);
  173. }
  174.  
  175. /*
  176.  * change the status of the player.  If he's living, we add special
  177.  * effects and do the cleanup from the last game. setup the right icons
  178.  * and grab all the io on the screen. If he's dead, release the IO
  179.  * from the screen and reset critical values.
  180.  */
  181. change_life(live_or_die)
  182. {
  183.     register int x, n, m = (live_or_die == -1)? 40 : 300;
  184.  
  185.     stop_timer();
  186.     if (live_or_die == LIVE) {
  187.     move_fuse(fuse = (struct region *)NULL); /* erase the last fuse */
  188.     if (region) {
  189.         pen_x = region->x, pen_y = region->y;
  190.         rm_cur_line(PIX_CLR); /* remove the current line drawn */
  191.     }
  192.     if (lives <= 0) {
  193.         if (play_mode == DEMO)
  194.         lives =  1;
  195.         else
  196.         lives = MAX_LIVES;
  197.         clear_board(); /* resets pen_x, pen_y */
  198.         level = -2, score = 0;
  199.     } else {
  200.         extern int qix1_x0[], qix1_x1[], qix1_y0[], qix1_y1[];
  201.         extern int qix2_x0[], qix2_x1[], qix2_y0[], qix2_y1[];
  202.  
  203.         draw(convert_x(qix1_x0[0]), convert_y(qix1_y0[0]),
  204.          convert_x(qix1_x1[0]), convert_y(qix1_y1[0]), PIX_CLR);
  205.         if (level >= 0)
  206.         draw(convert_x(qix2_x0[0]), convert_y(qix2_y0[0]),
  207.              convert_x(qix2_x1[0]), convert_y(qix2_y1[0]), PIX_CLR);
  208.     }
  209.     Speed = 3 + min(level/3, 3);
  210. #ifdef DEBUG
  211.     if (debug)
  212.         printf("Speed = %d\n", Speed);
  213. #endif DEBUG
  214.     clear_sparks();
  215.     update_score();
  216.     moving = STOP;
  217.     drawing = FALSE;
  218.     if (level > 0) {
  219.         msg("All scores now\n%d times\ntheir original value.", level+1);
  220.         sleep(3);
  221.         remove_msgs(0);
  222.     }
  223.     place_pen(); /* make pen appear */
  224.     }
  225.  
  226.     for (x = 0; x < 2; x++)
  227.     for (n = m; n >= 40 && n <= 300; n -= 5 * live_or_die)
  228.         box(pen_coord_x(pen_x)-n/2, pen_coord_y(pen_y)-n/2,
  229.         pen_coord_x(pen_x)+n/2, pen_coord_y(pen_y)+n/2, XOR);
  230.  
  231.     if (live_or_die == DIE) {
  232.     is_alive = FALSE;
  233.     if (--lives <= 0) {
  234.         reset_joystick_win(TRUE);
  235.         msg("Game Over.");
  236.         sleep(2);
  237.         /* if he got on the scoreboard, let him put his initials up */
  238.         if (play_mode == REAL_PLAY)
  239.         score_board(FALSE, FALSE);
  240.         if (play_mode == SHOW_SPIRAL)
  241.         time_left = 50; /* demo mode comes after spiral death trap */
  242.         else {
  243.         score_board(TRUE, FALSE);
  244.         play_mode = SHOW_SCORES;
  245.         time_left = 100; /* show scores after demo mode or real play */
  246.         }
  247.         moving = NO_MOVE;
  248.     } else {
  249.         moving = STOP;
  250.         drawing = 0;
  251.     }
  252.     place_pen(); /* erase pen */
  253.     } else {
  254.     is_alive = TRUE;
  255.     reset_joystick_win(FALSE);
  256.     }
  257.     start_timer();
  258. }
  259.  
  260. update_score()
  261. {
  262.     char buf[128];
  263.     int x;
  264.  
  265.     sprintf(buf, "Score: %6d", score);
  266.     pw_text(joystick_win, 500, 22, PIX_SRC, big_font, buf);
  267.     pw_text(joystick_win, 500, 22, PIX_SRC|PIX_DST, big_font, buf);
  268.  
  269.     if (play_mode != REAL_PLAY) {
  270.     pw_text(draw_win, 105, 12, PIX_SRC, small_font,
  271.         "Click RIGHT mouse button or use <spacebar> to start new game.");
  272.     return;
  273.     }
  274.  
  275.     pw_text(joystick_win, 500, 45, PIX_SRC, big_font, "Lives: ");
  276.     for (x = 0; x < MAX_LIVES; x++)
  277.     pw_rop(joystick_win, 575+(x*20), 32, 16,16, (x < lives-1)?
  278.         PIX_SRC:PIX_CLR, &pen_image, 0, 0);
  279.     sprintf(buf, "Filled: %d%%",(int)((double)area_closed/TOTAL_AREA*100));
  280.     pw_text(draw_win, 280, 12, PIX_SRC, small_font, buf);
  281.     pw_text(draw_win, 281, 12, PIX_SRC|PIX_DST, small_font, buf);
  282. }
  283.  
  284. Pixrect *save[15];  /* area under text to be redisplayed upon removal of text */
  285. int x_save[15], y_save, x_pos[15], y_pos[15];
  286. static int msgs;   /* the number of text lines displayed on the board */
  287.  
  288. /* print a message somewhere at the top of the playing board for two seconds */
  289. msg(fmt, args)
  290. char *fmt;
  291. {
  292.     char buf[BUFSIZ], *index();
  293.     register char *p2, *p = buf;
  294.  
  295.     y_save = l_height(big_font) + 1;
  296.  
  297.     vsprintf(buf, fmt, &args);
  298. #ifdef DEBUG
  299.     puts(buf);
  300. #endif DEBUG
  301.     do  {
  302.     if (p2 = index(p, '\n'))
  303.         *p2 = 0;
  304.     x_save[msgs] = strlen(p) * l_width(big_font) + 1;
  305.     x_pos[msgs] = BOARD_WIDTH_IN_PIXELS/2 - x_save[msgs]/2;
  306.     y_pos[msgs] = TOP_BORDER + (1+msgs) * 2 * y_save;
  307.  
  308.     if (!(save[msgs] = mem_create(x_save[msgs], y_save, 1))) {
  309.         puts("whoops! Out of memory... no sense going on with this.");
  310.         exit(1);
  311.     }
  312.     pr_rop(save[msgs], 0, 0, x_save[msgs], y_save, PIX_SRC,
  313.            draw_win->pw_prretained, x_pos[msgs], y_pos[msgs]);
  314.  
  315.     pw_text(draw_win, x_pos[msgs], y_pos[msgs]+l_height(big_font)-5,
  316.         PIX_SRC, big_font, p);
  317.     pw_text(draw_win, x_pos[msgs]+1, y_pos[msgs]+l_height(big_font)-5,
  318.         PIX_SRC|PIX_DST, big_font, p);
  319.     } while (++msgs < 15 && p2 && *(p = p2+1));
  320. }
  321.  
  322. /* remove all messages from the board and put back the images underneith */
  323. remove_msgs(clearing)
  324. {
  325.     while (msgs--) {
  326.     if (!clearing)
  327.         pw_rop(draw_win, x_pos[msgs], y_pos[msgs], x_save[msgs],  y_save,
  328.         PIX_SRC, save[msgs], 0, 0);
  329.     pr_destroy(save[msgs]);
  330.     }
  331.     msgs = 0;
  332. }
  333.  
  334. catch(sig)
  335. {
  336.     stop_timer();
  337.     if (sig == SIGXCPU) {
  338.     msg("CPU timelimit exceeded.  Go home and eat dinner.");
  339.     sleep(2);
  340.     remove_msgs(0);
  341.     return;
  342.     }
  343.     change_life(DIE);
  344.     if (sig == SIGSEGV)
  345.     fprintf(stderr, "Segmentation fault.\n");
  346.     else
  347.     fprintf(stderr, "Bus Error\n");
  348.     abort();
  349. }
  350.